// 数字重复统计
// · 随机产生100个整数
// · 数字的范围[-100, 100]
// · 降序输出这些生成的数字并打印其重复的次数

package main

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

// 方式一: 不使用 map (第 4 周)
func f1_non_map() {
	a := make([]int, 0, 100) // 存储 100 个随机数，长度从 0 开始，减少判断是否存在的查找时间
	b := make([]int, 0, 100) // 记录随机数出现的次数

	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	// 生成 100 个随机数并记录每个随机数出现的次数
	for i := 0; i < 100; i++ {
		v := r.Intn(201) - 100 // 随机数范围 [-100, 100]
		// fmt.Println(v)
		exists := false

		// 判断生成的随机数是否已存在
		for j := 0; j < len(a); j++ {
			if v == a[j] {
				// 随机数已存在，只增加出现次数
				b[j] += 1
				exists = true
				break
			}
		}

		if !exists {
			// 随机数不存在，追加，出现次数初始为 1
			a = append(a, v)
			b = append(b, 1)
		}
	}
	fmt.Println("排序前:")
	for i := 0; i < len(a); i++ {
		fmt.Printf("%3d(%d)", a[i], b[i])
		if (i+1)%10 == 0 {
			fmt.Println()
		} else {
			fmt.Printf(" ")
		}
	}
	fmt.Printf("\n\n")

	// 降序排序
	for i := 0; i < len(a)-1; i++ {
		for j := 0; j < len(a)-1-i; j++ {
			if a[j] > a[j+1] {
				// 值和次数同时移动
				a[j], a[j+1] = a[j+1], a[j]
				b[j], b[j+1] = b[j+1], b[j]
			}
		}
	}

	fmt.Println("排序后:")
	for i := 0; i < len(a); i++ {
		fmt.Printf("%3d(%d)", a[i], b[i])
		if (i+1)%10 == 0 {
			fmt.Println()
		} else {
			fmt.Printf(" ")
		}
	}
	fmt.Println()
}

// 方式二: 使用 map （第 6 周）
func f2_map() {
	var m = map[int]int{}

	// 生成 100 个随机数并统计出现次数
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < 100; i++ {
		k := r.Intn(201) - 100
		m[k] += 1
	}

	// 获取全部 key
	keys := make([]int, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}

	// 对 key 降序排列
	sort.Sort(sort.Reverse(sort.IntSlice(keys)))

	// 降序输出
	for _, k := range keys {
		fmt.Printf("%3d: %d\n", k, m[k])
	}
}

func main() {
	f1_non_map() // 非 map 实现
	// f2_map() // map 实现
}

// 批改意见
// 思路清晰，逻辑正确，两个知识点都用的非常好